/*
 * 文件名： WechatScanPayManager.java
 * 
 * 工程名称: bis-manager
 *
 * Gopay
 *
 * 创建日期： 2016年8月5日
 *
 * Copyright(C) 2016, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.manager.bank.scan;

import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.CmbcConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.ScanPayBaseMessage;
import com.gopay.common.domain.bank.wechat.scan.cmbc.FetchCheckAccntFile;
import com.gopay.common.domain.bank.wechat.scan.cmbc.Head;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantModify;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantOperation;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantOperationQuery;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantQuery;
import com.gopay.common.domain.bank.wechat.scan.cmbc.MerchantSettled;
import com.gopay.common.domain.bank.wechat.scan.cmbc.Refund;
import com.gopay.common.domain.bank.wechat.scan.cmbc.ScanPay;
import com.gopay.common.domain.bank.wechat.scan.cmbc.TradeQuery;
import com.gopay.common.domain.bank.wechat.scan.cmbc.TransMsg;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.cust.CustSettledInfo;
import com.gopay.common.exception.GopayException;
import com.gopay.common.user.dao.CustSettledInfoDao;
import com.gopay.remote.bank.businesses.CmbcScanPayService;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.DomDriver;

/**
 * 微信扫码业务报文拼装处理
 *
 * @author 蒋相蛟
 *
 * @version
 *
 * @since 2016年9月30日
 */
@SuppressWarnings("all")
public class CmbcWechatScanPayManager {

	private static Logger logger = LoggerFactory.getLogger(CmbcWechatScanPayManager.class);
	
	/**
	 * 注入对象
	 */
	@Resource(name = "wechatScanPayConfig")
	private Map<String, String> wechatScanPayConfig;

	@Resource(name = "cmbcWechatScanPayServiceClient")
	private CmbcScanPayService cmbcWechatScanPayServiceClient;
	
	@Resource(name = "custSettledInfoDao")
	private CustSettledInfoDao custSettledInfoDao;

	public Object scanPay(BaseMessage msg) throws GopayException {
		TransMsg<ScanPay> request = new TransMsg<ScanPay>();
		BeanUtils.copyProperties(msg, request);
		msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
		ScanPayBaseMessage message = (ScanPayBaseMessage) msg;
		CustSettledInfo info = custSettledInfoDao.getCustSettledInfo(msg.getCustomerID(),
				CmbcConstants.WECHAT_SETTLED, CmbcConstants.ZFB_SETTLED_SUCCESS);
		if (null == info) {
			logger.info(msg.getCustomerID() + ",此商户没有找到支付宝入驻帐号！");
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E1165);
		}
		ScanPay scanBody = new ScanPay();
		scanBody.setMerchantCode(info.getBankMerchantCode()); 
		//scanBody.setMerchantCode("2016092904504811"); // 测试用的商户银行代码--2016092904504811
		scanBody.setTotalAmount(message.getAmount().toString());
		scanBody.setSubject(message.getGoodsBody());
		scanBody.setDesc(message.getGoodsBody());
		// 1-限定不能使用信用卡支付，传空是使用信用卡
		if("0".equals(message.getLimitCreditPay())){
			scanBody.setLimitPay("");
		}else{
			scanBody.setLimitPay("1");
		}
		
		/**
		 * 订单失效时间目前是6分钟后失效
		 * 指定订单的支付有效时间（分钟数），超过有效时间用户将无法支付。若不指定该参数则系统默认设置24小时支付有效时间。参数允许设置范围：
		 * 1-1440区间的整数值，超过1440默认设置1440
		 */
		scanBody.setExpireTime(6);
		request.setHead(creatHead());
		request.setBody(scanBody);
		request.setPlainMessage(buildSignPlain(request, ScanPay.class));
		logger.info("CMBC scan manage pay send message: "+request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.payment(request);
	}

	public Object verify(BaseMessage msg) throws GopayException {
		boolean falg = false;
		falg = (boolean) cmbcWechatScanPayServiceClient.verify(msg);
		BankLogUtils.printWeChatManagerVerifyReturnLog(msg, falg);
		return falg;
	}

	@SuppressWarnings("unchecked")
	public Object orderQuery(BaseMessage msg) throws GopayException {
		TransMsg<TradeQuery> request = new TransMsg<TradeQuery>();
		BeanUtils.copyProperties(msg, request);
		TradeQuery queryBody = new TradeQuery();
		queryBody.setOriReqMsgId(msg.getBankOrderId());
		
		request.setHead(creatHead());
		request.setBody(queryBody);
		request.setPlainMessage(buildSignPlain(request, TradeQuery.class));

		logger.info("CMBC scan manage query send message: "+request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.queryOrder(request);
	}

	public Object refund(BaseMessage msg) throws GopayException {
		TransMsg<Refund> request = new TransMsg<Refund>();
		msg.setBankOrderId(modifyOrderId(msg.getOrderId()));
		BeanUtils.copyProperties(msg, request);
		Refund refundBody = new Refund();
		// 原交易订单号
		refundBody.setOriReqMsgId(msg.getTkOriBankOrderId());
		refundBody.setRefundAmount(msg.getAmount());
		
		request.setHead(creatHead());
		request.setBody(refundBody);
		request.setPlainMessage(buildSignPlain(request, Refund.class));

		logger.info("CMBC scan manage refund send message: "+request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.refund(request);
	}

	/**
	 * 民生的查询接口包括撤销订单、退款订单、支付类订单的查询
	 */
	public Object refundQuery(BaseMessage msg) throws GopayException {
		TransMsg<TradeQuery> request = new TransMsg<TradeQuery>();
		BeanUtils.copyProperties(msg, request);
		TradeQuery queryBody = new TradeQuery();
		queryBody.setOriReqMsgId(msg.getOrderId());
		
		request.setHead(creatHead());
		request.setBody(queryBody);
		request.setPlainMessage(buildSignPlain(request, TradeQuery.class));

		logger.info("CMBC scan manage refundQuery send message: "+request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.refundQuery(request);
	}

	public Object merchantSettled(MerchantSettled msg, Map<String,String> param)
			throws GopayException {
		TransMsg<MerchantSettled> request = new TransMsg<MerchantSettled>();
		request.setHead(creatHead());
		request.setBody(msg);
		request.setPrivateKeyPath(param.get("privateKeyPath"));
		request.setPublicKeyPath(param.get("publicKeyPath"));
		request.setPayUrl(param.get("url"));
		request.setPlainMessage(buildSignPlain(request, MerchantSettled.class));
		/**
		 * 设置回调地址
		 */
		request.setPayRuturnUrl(wechatScanPayConfig.get("WECHATSCAN.MERCHANT.CALLBACK.URL"));
		logger.info("-----CMBC SCAN Merchant Settled Send Msg :" + request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.merchantSettled(request);
	}

	public Object getCheckAccountFile(String date, String fileType,Map<String,String> param)
			throws GopayException {
		TransMsg request = new TransMsg();
		FetchCheckAccntFile fectFileBody = new FetchCheckAccntFile();
		fectFileBody.setSettleDate(date);
		fectFileBody.setFileType(fileType);
		request.setHead(creatHead());
		request.setBody(fectFileBody);
		request.setPlainMessage(buildSignPlain(request, FetchCheckAccntFile.class));

		request.setPrivateKeyPath(param.get("privateKeyPath"));
		request.setPublicKeyPath(param.get("publicKeyPath"));
		request.setPayUrl(param.get("url"));
		request.setOutStlmCd(param.get("payType"));
		logger.info("------CMBC SCAN fetch CheckAccntFile Send Msg :" + request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.getCheckAccountFile(request);
	}

	public Object merchantQuery(MerchantQuery msg,Map<String,String> param) throws GopayException {
		TransMsg request = new TransMsg();
		request.setHead(creatHead());
		request.setBody(msg);
		request.setPlainMessage(buildSignPlain(request, MerchantQuery.class));

		request.setPrivateKeyPath(param.get("privateKeyPath"));
		request.setPublicKeyPath(param.get("publicKeyPath"));
		request.setPayUrl(param.get("url"));

		logger.info("--------CMBC WECHAT fetch CheckAccntFile Send Msg :" + request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.merchantQuery(request);
	}

	public Object merchantModify(MerchantModify msg,Map<String,String> param)
			throws GopayException {
		TransMsg request = new TransMsg();
		request.setHead(creatHead());
		request.setBody(msg);
		request.setPlainMessage(buildSignPlain(request, MerchantModify.class));

		request.setPrivateKeyPath(param.get("privateKeyPath"));
		request.setPublicKeyPath(param.get("publicKeyPath"));
		request.setPayUrl(param.get("url"));

		logger.info("------CMBC WECHAT Modify Merchant Send Msg :" + request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.merchantModify(request);
	}
	/**
	 * 
	 * 功能描述：商户配置报文构建
	 *
	 * @param msg
	 * @param param
	 * @return
	 * @throws GopayException
	 * 
	 * @author 宣广海
	 *
	 * @since 2017年7月20日
	 *
	 * @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
	 */
	public Object merchantOperation(MerchantOperation msg, Map<String,String> param)
			throws GopayException {
		TransMsg<MerchantOperation> request = new TransMsg<MerchantOperation>();
		request.setHead(creatHead());
		request.setBody(msg);
		request.setPrivateKeyPath(param.get("privateKeyPath"));
		request.setPublicKeyPath(param.get("publicKeyPath"));
		request.setPayUrl(param.get("url"));
		request.setPlainMessage(buildSignPlain(request, MerchantOperation.class));
		logger.info("-----CMBC SCAN merchantOperation Send Msg :" + request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.merchantOperation(request);
	}
	public Object merchantOperationQuery(MerchantOperationQuery msg, Map<String,String> param)
			throws GopayException {
		TransMsg<MerchantOperationQuery> request = new TransMsg<MerchantOperationQuery>();
		request.setHead(creatHead());
		request.setBody(msg);
		request.setPrivateKeyPath(param.get("privateKeyPath"));
		request.setPublicKeyPath(param.get("publicKeyPath"));
		request.setPayUrl(param.get("url"));
		request.setPlainMessage(buildSignPlain(request, MerchantOperation.class));
		logger.info("-----CMBC SCAN merchantOperationQuery Send Msg :" + request.getPlainMessage());
		return cmbcWechatScanPayServiceClient.merchantOperationQuery(request);
	}
	/**
	 * @Description: 拼装加密报文
	 * @param obj
	 * @return
	 * @throws Exception
	 * @author w_jiqing
	 */
	public String buildSignPlain(Object obj, Class bodyCla) {
		// 去掉多一个下划线的问题
		XStream xstream = new XStream(new DomDriver("UTF-8", new NoNameCoder()));
		// bodyCla：请求的XML报文Body对应的class类型
		xstream.alias("body", bodyCla, bodyCla.getSuperclass());
		xstream.alias("merchant", TransMsg.class);
		xstream.processAnnotations(obj.getClass());
		return xstream.toXML(obj);
	}

	public Head creatHead() {
		Head head = new Head();
		head.setVersion("1.0.0");
		head.setMsgType("01");
		head.setReqDate(new DateTime().toString("yyyyMMddHHmmss"));
		return head;
	}
	
	/**
	 * @Description: 替换国付宝订单号前2位为WF
	 * @param orderId
	 * @return
	 * @author jxj
	 */
	private static String modifyOrderId(String orderId) {

		return "MS" + orderId.substring(2);

	}
}
